package com.study.dynamic.controller;

import com.study.dynamic.context.CustomApplicationContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.Date;
import java.util.Objects;
import java.util.Random;

/**
 * @author Mayjean
 * @Date2020/9/11
 */
@RestController
@RequestMapping("/redis")
public class RedisDynamicController {


    @Autowired
    private CustomApplicationContext customApplicationContext;


    @GetMapping(value = "/load1" )
    public String load1(){
        getBean();
        createStringRedisTemplate("127.0.0.1",6378,null);
        getBean();
        return "SUCCESS 1:"+new Date();
    }

    @GetMapping(value = "/load2" )
    public String load2(){
        getBean();
        createStringRedisTemplate("127.0.0.1",6379,null);
        getBean();
        return "SUCCESS 2:"+new Date();
    }

    private void getBean(){
        /**
         * 配置启动不加载redis: @SpringBootApplication(exclude = RedisAutoConfiguration.class),
         * 否则系统会自动加载redis默认配置,比如ip、port、序列化方式
         * 启动配置了不自动装载,则通过获取bean的时候会抛异常来进行判断：
         * org.springframework.beans.factory.NoSuchBeanDefinitionException:
         * No qualifying bean of type 'org.springframework.data.redis.core.StringRedisTemplate' available
         */
        StringRedisTemplate stringRedisTemplate = customApplicationContext.getBean(StringRedisTemplate.class);
        if(Objects.isNull(stringRedisTemplate)){
            System.out.println("redis连接未加载,请加载后再试");
            return;
        }
        System.out.println(stringRedisTemplate +"    "+stringRedisTemplate.opsForValue().get("name"));
        stringRedisTemplate.opsForValue().set("name","你好:"+new Random().nextInt(1000));
    }

    private void createStringRedisTemplate(String host,int port ,String password){
        //判断连接的是否为同一个redis
        StringRedisTemplate sysCurrentStringRedisTemplate = customApplicationContext.getBean(StringRedisTemplate.class);
        if (Objects.nonNull(sysCurrentStringRedisTemplate)) {
            RedisConnectionFactory redisConnectionFactory = sysCurrentStringRedisTemplate.getConnectionFactory();
            if(redisConnectionFactory instanceof LettuceConnectionFactory) {
                LettuceConnectionFactory lettuceConnectionFactory = (LettuceConnectionFactory)redisConnectionFactory;
                if(Objects.equals(lettuceConnectionFactory.getHostName(),host) && Objects.equals(lettuceConnectionFactory.getPort(),port)){
                    System.out.println("redis连接相同,不切换连接");
                    return;
                }
            }
        }

        LettuceConnectionFactory connectionFactory = new LettuceConnectionFactory(host,port);
        connectionFactory.afterPropertiesSet();
        connectionFactory.validateConnection();

        StringRedisTemplate stringRedisTemplate = redisTemplate(connectionFactory);
        customApplicationContext.registerSingleton("stringRedisTemplate",stringRedisTemplate);
    }

    /**
     * redis自动装配类RedisAutoConfiguration
     * @param factory
     * @return
     */
    public StringRedisTemplate redisTemplate(RedisConnectionFactory factory) {
        StringRedisTemplate template = new StringRedisTemplate();
        template.setConnectionFactory(factory);
//        Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
//        ObjectMapper om = new ObjectMapper();
//        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
//        om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
//        jackson2JsonRedisSerializer.setObjectMapper(om);
        StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
        // key采用String的序列化方式
        template.setKeySerializer(stringRedisSerializer);
        // hash的key也采用String的序列化方式
        template.setHashKeySerializer(stringRedisSerializer);
        // value序列化方式采用jackson
        template.setValueSerializer(stringRedisSerializer);
        // hash的value序列化方式采用jackson
        template.setHashValueSerializer(stringRedisSerializer);
        template.afterPropertiesSet();
        return template;
    }
}